package gin

import (
	"e-commerce/services/auth-service/internal/service"
	"fmt"
	"log"
	"net/http"
	"os"

	productpb "e-commerce/services/product-service/api/pb"

	"github.com/gin-gonic/gin"
	"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/metadata"
	"gopkg.in/yaml.v3"
)

type AuthHandler struct {
	AuthService   *service.AuthService
	ProductClient *ProductClient
}

type ProductClient struct {
	client productpb.ProductServiceClient
	conn   *grpc.ClientConn
}

type Config struct {
	ProductService product_service `yaml:"product_service"`
}

type product_service struct {
	Addr string `yaml:"addr"`
}

func NewProductClient(configPath string) (*ProductClient, error) {
	yamlFile, err := os.ReadFile(configPath)
	if err != nil {
		return nil, fmt.Errorf("failed to read config file: %v", err)
	}
	var config Config
	err = yaml.Unmarshal(yamlFile, &config)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal config file: %v", err)
	}
	conn, err := grpc.NewClient(
		config.ProductService.Addr,
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		//添加otel遥测
		grpc.WithStatsHandler(otelgrpc.NewClientHandler()),
	)
	if err != nil {
		return nil, fmt.Errorf("failed to create auth service client: %v", err)
	}
	productClient := &ProductClient{
		client: productpb.NewProductServiceClient(conn),
		conn:   conn,
	}
	return productClient, nil
}

func (c *ProductClient) Close() error {
	if c.conn != nil {
		return c.conn.Close()
	}
	return nil
}

func (h *AuthHandler) Register(c *gin.Context) {
	var req struct {
		Username string `json:"username"`
		Password string `json:"password"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
		return
	}

	err := h.AuthService.Register(req.Username, req.Password)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Registration failed"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"success": true})
}

func (h *AuthHandler) Login(c *gin.Context) {
	var req struct {
		Username string `json:"username"`
		Password string `json:"password"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
		return
	}

	token, err := h.AuthService.Login(req.Username, req.Password)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid credentials"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"token": token})
}

func (h *AuthHandler) ValidateToken(c *gin.Context) {
	token := c.GetHeader("Authorization")
	if token == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Missing authorization token"})
		return
	}

	valid, userID, role := h.AuthService.ValidateToken(token)
	if !valid {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"token": token, "user_id": userID, "role": role})
}

func (h *AuthHandler) Logout(c *gin.Context) {
	token := c.GetHeader("Authorization")
	if token == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Missing authorization token"})
		return
	}

	err := h.AuthService.Logout(token)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Logout failed"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"success": true})
}

func (h *AuthHandler) Remove(c *gin.Context) {
	token := c.GetHeader("Authorization")
	if token == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Missing authorization token"})
		return
	}

	err := h.AuthService.Remove(token)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Remove failed"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"token": token, "message": "删除成功"})
}

func (h *AuthHandler) CreateProduct(c *gin.Context) {
	token := c.GetHeader("Authorization")
	if token == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Missing authorization token"})
		return
	}

	var product productpb.Product
	if err := c.ShouldBindJSON(&product); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
		return
	}

	ctx := c.Request.Context()
	//往ctx中添加token
	newCtx := metadata.NewOutgoingContext(ctx, metadata.New(map[string]string{
		"authorization": token,
	}))
	_, err := h.ProductClient.client.CreateProduct(newCtx, &productpb.CreateProductRequest{
		Product: &product,
	})
	if err != nil {
		// h.ProductClient.Close()
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	// h.ProductClient.Close()
	c.JSON(http.StatusOK, gin.H{"success": true})
}

func NewAuthHandler(configPath string) *AuthHandler {
	authService, err := service.NewAuthService(configPath)
	if err != nil {
		log.Fatalf("Failed to create auth service: %v", err)
	}
	productClient, err := NewProductClient(configPath)
	if err != nil {
		log.Fatalf("Failed to create product client: %v", err)
	}
	return &AuthHandler{
		AuthService:   authService,
		ProductClient: productClient,
	}
}

// func (h *AuthHandler) AuthMiddleware() gin.HandlerFunc {
// 	return func(c *gin.Context) {
// 		token := c.GetHeader("Authorization")
// 		if token == "" {
// 			c.JSON(http.StatusUnauthorized, gin.H{"error": "Missing authorization token"})
// 			c.Abort()
// 			return
// 		}
// 		valid, userID, role := h.AuthService.ValidateToken(token)
// 		if !valid {
// 			c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
// 			c.Abort()
// 			return
// 		}
// 		c.Set("user_id", userID)
// 		c.Set("role", role)
// 		c.Next()
// 	}
// }
